home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / util / cli / HowDif.lha / HowDif / source / howdif.c next >
C/C++ Source or Header  |  2002-10-14  |  10KB  |  304 lines

  1. /* HowDif 2.0 for Amiga
  2.  
  3.    Quick-and-dirty routine written to compare two files. The assumption is
  4.    that they are files known to be different from one another, already. I
  5.    want to know HOW different they are from one another. Essentially, this
  6.    program just reads two files, notes the number of bytes read, and notes
  7.    how many bytes do not match. (This is a strict byte-for-byte comparison.)
  8.  
  9.    Written by James Jacobs and Ward Shrake
  10.    Last update: October 13, 2002 */
  11.  
  12. #include <exec/types.h>
  13. #include <dos/dos.h>
  14.  
  15. #include <stdlib.h>          /* EXIT_SUCCESS, EXIT_FAILURE */
  16.  
  17. typedef signed char  FLAG;   /* 8-bit signed quantity (replaces BOOL) */
  18. typedef signed char  SBYTE;  /* 8-bit signed quantity (replaces Amiga BYTE) */
  19. typedef signed short SWORD;  /* 16-bit signed quantity (replaces Amiga WORD) */
  20. typedef signed long  SLONG;  /* 32-bit signed quantity (same as LONG) */
  21. #define elif         else if
  22. #define AGLOBAL      ;       /* global (project-scope) */
  23. #define MODULE       static  /* external static (file-scope) */
  24. #define PERSIST      static  /* internal static (function-scope) */
  25. #define AUTO         auto    /* automatic (function-scope) */
  26.  
  27. #define BYTESPERLINE 14
  28.  
  29. MODULE STRPTR                MemoryPtr[3]  = {NULL, NULL};
  30. MODULE struct FileInfoBlock* FIBPtr        = NULL;
  31. MODULE BPTR                  FileHandle    = NULL;
  32. MODULE TEXT                  output[1024 + 1],
  33.                              ansi1[20],
  34.                              ansi2[20];
  35. MODULE FLAG                  inverted      = FALSE;
  36. MODULE ULONG                 size[3];
  37.  
  38. MODULE void cleanexit(SLONG rc);
  39. MODULE void hexalize(UBYTE data);
  40. MODULE void invert(void);
  41. MODULE void deinvert(void);
  42.  
  43. int main(int argc, char** argv)
  44. {   AUTO    ULONG  i, j,
  45.                    length,
  46.                    percent1, percent2,
  47.                    br,
  48.                    bw = 0;     // number of total mismatches found
  49.     AUTO    FLAG   compare;
  50.     PERSIST TEXT   arcadia[] = " /\\abcdefghijklm0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.,+$nopqrstu";
  51.     AUTO    STRPTR primary, secondary;
  52.  
  53.     if (0)
  54.     {   Printf("$VER: HowDif 2.0 for Amiga (13.10.2002)");
  55.     }
  56.  
  57.     ansi1[0] = 0x9b;
  58.     ansi1[1] = 0;
  59.     strcat(ansi1, "0;32;40;>0m"); // means `go white on grey'
  60.  
  61.     ansi2[0] = 0x9b;
  62.     ansi2[1] = 0;
  63.     strcat(ansi2, "0;39;39;>0m"); // means `go back to vanilla'
  64.  
  65.     Printf("HowDif 2.0 for Amiga\n\n");
  66.  
  67.     if (argc == 2)
  68.     {   compare = FALSE;
  69.     } elif (argc == 3)
  70.     {   compare = TRUE;
  71.     } else
  72.     {   Printf("Usage: %s <file1> <file2>\n", argv[0]);
  73.         cleanexit(EXIT_FAILURE);
  74.     }
  75.  
  76.     for (i = 0; i <= 1; i++)
  77.     {   if (i == 0 || compare)
  78.         {   if (!(FileHandle = (BPTR) Lock(argv[i + 1], ACCESS_READ)))
  79.             {   Printf("Can't lock %s!\n", argv[i + 1]);
  80.                 exit(EXIT_FAILURE);
  81.             }
  82.             if (!(FIBPtr = AllocDosObject(DOS_FIB, NULL)))
  83.             {   UnLock(FileHandle);
  84.                 Printf("Can't allocate DOS object!\n");
  85.                 exit(EXIT_FAILURE);
  86.             }
  87.             if (!(Examine(FileHandle, FIBPtr)))
  88.             {   FreeDosObject(DOS_FIB, FIBPtr);
  89.                 UnLock(FileHandle);
  90.                 Printf("Can't examine %s!\n", argv[i + 1]);
  91.             }
  92.             size[i] = FIBPtr->fib_Size;
  93.             FreeDosObject(DOS_FIB, FIBPtr);
  94.             FIBPtr = NULL;
  95.             UnLock(FileHandle);
  96.             FileHandle = NULL;
  97.             if (!(MemoryPtr[i] = AllocMem(size[i], NULL)))
  98.             {   Printf("Out of memory!\n");
  99.                 cleanexit(EXIT_FAILURE);
  100.             }
  101.             if (!(FileHandle = (BPTR) Open(argv[i + 1], MODE_OLDFILE)))
  102.             {   Printf("Can't open %s for reading!\n", argv[i + 1]);
  103.                 cleanexit(EXIT_FAILURE);
  104.             }
  105.             if (Read(FileHandle, MemoryPtr[i], size[i]) != size[i])
  106.             {   Printf("Can't read from %s!\n", argv[i + 1]);
  107.                 cleanexit(EXIT_FAILURE);
  108.             }
  109.             Close(FileHandle);
  110.             FileHandle = NULL;
  111.     }   }
  112.  
  113.     if (compare)
  114.     {   if (size[0] > size[1])
  115.         {   size[2] = size[0];
  116.             size[0] = size[1];
  117.             size[1] = size[2];
  118.             MemoryPtr[2] = MemoryPtr[0];
  119.             MemoryPtr[0] = MemoryPtr[1];
  120.             MemoryPtr[1] = MemoryPtr[2];
  121.             primary   = argv[2];
  122.             secondary = argv[1];
  123.         } else
  124.         {   primary   = argv[1];
  125.             secondary = argv[2];
  126.         }
  127.         Printf("  Primary file is %s (%ld bytes).\n",     primary, size[0]);
  128.         Printf("Secondary file is %s (%ld bytes).\n\n", secondary, size[1]);
  129.  
  130.         for (br = 0; br < size[0]; br++) // do this loop as long as the file has not ended
  131.         {   if (MemoryPtr[0][br] != MemoryPtr[1][br]) // compare the two single bytes
  132.             {   bw++;    // add one to the counter showing # of mismatches
  133.     }   }   }
  134.     else
  135.     {   Printf("File is %s (%ld bytes).\n\n", argv[1], size[0]);
  136.     }
  137.  
  138.     if (size[0] > 65535)
  139.     {   Printf("  ");
  140.     }
  141.     Printf("       0011 2233 4455 6677 8899 AABB CCDD 0123456789ABCD 0123456789ABCD\n");
  142.     if (size[0] > 65535)
  143.     {   Printf("  ");
  144.     }
  145.     Printf("       ---------------------------------- -------------- --------------\n");
  146.  
  147.     for (i = 0; i < size[0]; i += BYTESPERLINE)
  148.     {   output[0] = 0;
  149.         deinvert();
  150.         strcat(output, "$");
  151.  
  152.         if (size[0] > 65535)
  153.         {   hexalize(i / 16777216); // do 1st byte
  154.             j = i % 16777216;       // remove 1st byte
  155.             hexalize(j / 65536);    // do 2nd byte
  156.             j %= 65536;             // remove 2nd byte
  157.         } else
  158.         {   j = i;
  159.         }
  160.         hexalize(j / 256);      // do 3rd byte
  161.         hexalize(j % 256);      // do 4th byte
  162.  
  163.         strcat(output, ": ");
  164.         for (j = 0; j < BYTESPERLINE; j++)
  165.         {   if (size[0] > i + j)
  166.             {   if (compare)
  167.                 {   if (MemoryPtr[0][i + j] != MemoryPtr[1][i + j])
  168.                     {   deinvert();
  169.                     } else
  170.                     {   invert();
  171.                 }   }
  172.                 hexalize(MemoryPtr[0][i + j]);
  173.             } else
  174.             {   deinvert();
  175.                 strcat(output, "##");
  176.             }
  177.             if (j % 2)
  178.             {   deinvert();
  179.                 strcat(output, " ");
  180.         }   }
  181.  
  182.         for (j = 0; j < BYTESPERLINE; j++)
  183.         {   if (size[0] > i + j)
  184.             {   if (compare)
  185.                 {   if (MemoryPtr[0][i + j] != MemoryPtr[1][i + j])
  186.                     {   deinvert();
  187.                     } else
  188.                     {   invert();
  189.                 }   }
  190.                 if
  191.                 (    MemoryPtr[0][i + j] < ' '
  192.                  || (MemoryPtr[0][i + j] >= 0x80 && MemoryPtr[0][i + j] <= 0x9F)
  193.                 ) // if an unprintable character
  194.                 {   strcat(output, ".");
  195.                 } else
  196.                 {   length = strlen(output);
  197.                     output[length] = MemoryPtr[0][i + j];
  198.                     output[length + 1] = 0;
  199.             }   }
  200.             else
  201.             {   deinvert();
  202.                 strcat(output, "#");
  203.         }   }
  204.  
  205.         deinvert();
  206.         strcat(output, " ");
  207.  
  208.         for (j = 0; j < BYTESPERLINE; j++)
  209.         {   if (size[0] > i + j)
  210.             {   if (compare)
  211.                 {   if (MemoryPtr[0][i + j] != MemoryPtr[1][i + j])
  212.                     {   deinvert();
  213.                     } else
  214.                     {   invert();
  215.                 }   }
  216.                 if (MemoryPtr[0][i + j] < 64)
  217.                 {   length = strlen(output);
  218.                     output[length] = arcadia[MemoryPtr[0][i + j]];
  219.                     output[length + 1] = 0;
  220.                 } else strcat(output, ".");
  221.             } else
  222.             {   deinvert();
  223.                 strcat(output, "#");
  224.         }   }
  225.  
  226.         deinvert();
  227.         Printf("%s\n", output);
  228.     }
  229.  
  230.     // when the program is all done comparing, print a summary report onscreen
  231.  
  232.     Printf("\nTotal bytes read: %ld\n", size[0]);
  233.  
  234.     if (compare)
  235.     {   Printf("Mismatches found: %ld\n", bw);
  236.  
  237.         /* calculate percentage:
  238.             percent1 is the percentage magnified 1 million times.
  239.             eg. 1 million = 1%, 100 million = 100%, 56,723,432 = 56.723432%.
  240.             By scaling in this way we preserve precision whilst avoiding
  241.             the need for true floating point mathematics.
  242.             percent2 is the actual integer percentage. */
  243.     
  244.         if (!bw)
  245.         {   percent2 = 0;
  246.         } else
  247.         {   percent1 = (100000000L / size[0]) * bw;
  248.             percent2 = percent1 / 1000000L;
  249.         }
  250.         Printf("Difference:       %ld%%\n", percent2);
  251.     }
  252.  
  253.     cleanexit(EXIT_SUCCESS); // end of the program. go back to DOS
  254. }
  255.  
  256. MODULE void invert(void)
  257. {   if (!inverted)
  258.     {   strcat(output, ansi1);
  259.         inverted = TRUE;
  260. }   }
  261. MODULE void deinvert(void)
  262. {   if (inverted)
  263.     {   strcat(output, ansi2);
  264.         inverted = FALSE;
  265. }   }
  266.  
  267. MODULE void cleanexit(SLONG rc)
  268. {   if (FIBPtr)
  269.     {   FreeDosObject(DOS_FIB, FIBPtr);
  270.     }
  271.     if (FileHandle)
  272.     {   Close(FileHandle);
  273.     }
  274.     if (MemoryPtr[0])
  275.     {   FreeMem(MemoryPtr[0], size[0]);
  276.     }
  277.     if (MemoryPtr[1])
  278.     {   FreeMem(MemoryPtr[1], size[1]);
  279.     }
  280.     exit(EXIT_SUCCESS);
  281. }
  282.  
  283. MODULE void hexalize(UBYTE data)
  284. {   TEXT tempstring[3];
  285.  
  286.     // Converts an unsigned byte into a hexadecimal string
  287.  
  288.     // do the high byte
  289.     if (data / 16 >= 10)
  290.     {   tempstring[0] = (data / 16) - 10 + 'A'; // must be done in this order to prevent overflow during calculation of the value
  291.     } else
  292.     {   tempstring[0] = (data / 16) + '0';
  293.     }
  294.  
  295.     // now the low byte
  296.     if (data % 16 >= 10)
  297.     {   tempstring[1] = (data % 16) - 10 + 'A';
  298.     } else
  299.     {   tempstring[1] = (data % 16) + '0';
  300.     }
  301.     tempstring[2] = 0;
  302.     strcat(output, tempstring);
  303. }
  304.